package com.kun.companion.core.ui.component;

import cn.hutool.core.util.StrUtil;
import com.kun.companion.core.AbstractApplication;
import com.kun.companion.core.context.ContextService;
import com.kun.companion.core.thread.ComThreadPool;
import com.kun.companion.core.ui.KunComponent;
import com.kun.companion.core.util.ComUtil;
import com.kun.companion.core.util.ResourceLoader;
import javafx.concurrent.Worker;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebView;
import netscape.javascript.JSObject;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import org.jsoup.nodes.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * TODO
 *
 * @author gzc
 * @since 2025/2/24 4:28
 **/
public class AiChatPane extends StackPane implements KunComponent {
    private static final Logger log = LoggerFactory.getLogger(AiChatPane.class);
    protected final String copyJsText = ResourceLoader.readResourceFile("/com/kun/companion/js/ai-chat-view.js", AbstractApplication.class);
    protected final String baseCss = ResourceLoader.readResourceFile("/com/kun/companion/css/ai-chat-view.css", AbstractApplication.class);
    // 每段时间吐出的字数
    protected int maxChunk = 1;
    protected int minChunk = 1;

    protected final WebView webView = new WebView();
    protected final Parser markdownParser = Parser.builder().build();
    protected final HtmlRenderer htmlRenderer = HtmlRenderer.builder().build();
    protected final List<MarkdownPlugin> pluginList = new ArrayList<>(16);

    private final ComThreadPool comThreadPool;
    private Future<?> currentTypingTask;
    private final AtomicBoolean isTyping = new AtomicBoolean(false);
    private final AtomicInteger progressPointer = new AtomicInteger(0);
    private final StringBuilder contentBuffer = new StringBuilder(8192);

    private Document htmlDocument;

    public AiChatPane() {
        comThreadPool = ContextService.getBean(ComThreadPool.class);
        // 初始化WebView
        initializeWebView();
        // 初始化组件布局
        initComponentLayout();

    }

    /**
     * 初始化WebView
     */
    private void initializeWebView() {
        // 禁用右键菜单
        webView.setContextMenuEnabled(false);
        webView.getEngine().getLoadWorker().stateProperty().addListener((obs, old, state) -> {
            if (state == Worker.State.SUCCEEDED) {
                // 注入桥接对象
                JSObject window = (JSObject) webView.getEngine().executeScript("window");
                window.setMember("javaLogger", new JsLogger());

                // 重写console.log
                String jsOverride = """
                        console.log = function(message) {
                            javaLogger.log(message);
                        };
                        """;
                webView.getEngine().executeScript(jsOverride);
                // 注入css和js代码
                injectStyleAndScript();
            }
        });
        // 加载html模板
        webView.getEngine().loadContent(buildHtmlTemplate());
    }

    /**
     * 组件布局初始化
     */
    protected void initComponentLayout() {
        webView.setPrefSize(800, 600);
        webView.setStyle("-fx-background-color: transparent;");
        getChildren().addAll(webView);
    }

    /**
     * 构建HTML页面模板（可重写扩展）
     */
    protected String buildHtmlTemplate() {
        return "<html><head></head><body><div id='content'></div></body></html>";
    }


    private void injectStyleAndScript() {
        String escapedCss = buildGlobalCSS().replace("'", "\\'").replace("\n", "\\n").replace("\r", "\\r");
        String initScript = String.format("""
                (function() {
                  const style = document.createElement('style');
                  style.textContent = '%s';
                  document.head.appendChild(style);
                  %s
                })()
                """, escapedCss, buildCopyScript());
        webView.getEngine().executeScript(initScript);
    }

    public void addRightMessage(String message) {
        String rightHtmlTemplate = "<div class=\"general-block\"></div>";
    }

    public void addLeftMessage(String message) {

    }

    public void startTyping(String text) {
        startTyping(text, 1000);
    }

    public void startTyping(String text, int speed) {
        if (StrUtil.isBlank(text)) {
            return;
        }
        if (!isTyping.compareAndSet(false, true)) {
            return;
        }
        progressPointer.set(0);
        contentBuffer.setLength(0);
        currentTypingTask = comThreadPool.submit(() -> {
            try {
                final int delay = 1000 / speed;
                final int totalLength = text.length();
                while (progressPointer.get() < totalLength && isTyping.get()) {
                    // 计算吐出的字符串
                    int remaining = text.length() - progressPointer.get();
                    int chunk = Math.min(maxChunk, Math.max(minChunk, remaining));
                    contentBuffer.append(text, progressPointer.get(), progressPointer.addAndGet(chunk));
                    // 更新页面
                    updateWebView(contentBuffer.toString());
                    // 停顿
                    TimeUnit.MILLISECONDS.sleep(delay);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                isTyping.set(false);
            }
        });
    }

    public void stopTyping() {
        if (currentTypingTask != null && !currentTypingTask.isDone()) {
            currentTypingTask.cancel(true);
        }
        isTyping.set(false);
    }

    /**
     * 更新WebView显示内容
     */
    private void updateWebView(String content) {
        String processedHtml = renderContent(content);
        ComUtil.uiThreadRun(() -> {
            webView.getEngine().loadContent(processedHtml);
        });
    }

    /**
     * 渲染内容到WebView（可重写实现自定义渲染逻辑）
     *
     * @param content 原始文本内容
     * @return 处理后的HTML内容
     */
    protected String renderContent(String content) {
        Node document = markdownParser.parse(content);
        String html = htmlRenderer.render(document);
        // 增强代码块包装逻辑
        html = html.replaceAll("(?i)<pre>", "<div class=\"code-block\"><pre>").replaceAll("(?i)</pre>", "</pre></div>");
        return applyPlugins(html);
    }

    /**
     * 应用注册的Markdown插件处理
     */
    private String applyPlugins(String html) {
        for (MarkdownPlugin plugin : pluginList) {
            html = plugin.process(html);
        }
        return html;
    }

    private String escapeHtml(String input) {
        return input.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace("\"", "&quot;").replace("'", "&#39;");
    }

    protected String buildCopyScript() {
        return copyJsText;
    }

    /**
     * 构建全局CSS样式（可重写扩展）
     */
    protected String buildGlobalCSS() {
        return baseCss;
    }


    @Override
    public void dispose() {

    }
}
